home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Freeware 2002 November
/
SGI Freeware 2002 November - Disc 1.iso
/
dist
/
fw_emacs-lisp-intro.idb
/
usr
/
freeware
/
info
/
emacs-lisp-intro.info-13.z
/
emacs-lisp-intro.info-13
Wrap
Text File
|
2002-07-08
|
50KB
|
1,258 lines
This is emacs-lisp-intro.info, produced by makeinfo version 4.0b from
emacs-lisp-intro.texi.
INFO-DIR-SECTION Emacs
START-INFO-DIR-ENTRY
* Emacs Lisp Intro: (eintr).
A simple introduction to Emacs Lisp programming.
END-INFO-DIR-ENTRY
This is an introduction to `Programming in Emacs Lisp', for people
who are not programmers.
Edition 2.04, 2001 Dec 17
Copyright (C) 1990, '91, '92, '93, '94, '95, '97, 2001 Free Software
Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1 or
any later version published by the Free Software Foundation; with the
Invariant Section being the Preface, with the Front-Cover Texts being
no Front-Cover Texts, and with the Back-Cover Texts being no Back-Cover
Texts. A copy of the license is included in the section entitled "GNU
Free Documentation License".
File: emacs-lisp-intro.info, Node: Mode Line, Prev: Miscellaneous, Up: Emacs Initialization
A Modified Mode Line
====================
Finally, a feature I really like: a modified mode line.
When I work over a network, I forget which machine I am using. Also,
I tend to I lose track of where I am, and which line point is on.
So I reset my mode line to look like this:
-:-- foo.texi rattlesnake:/home/bob/ Line 1 (Texinfo Fill) Top
I am visiting a file called `foo.texi', on my machine `rattlesnake'
in my `/home/bob' buffer. I am on line 1, in Texinfo mode, and am at
the top of the buffer.
My `.emacs' file has a section that looks like this:
;; Set a Mode Line that tells me which machine, which directory,
;; and which line I am on, plus the other customary information.
(setq default-mode-line-format
(quote
(#("-" 0 1
(help-echo
"mouse-1: select window, mouse-2: delete others ..."))
mode-line-mule-info
mode-line-modified
mode-line-frame-identification
" "
mode-line-buffer-identification
" "
(:eval (substring
(system-name) 0 (string-match "\\..+" (system-name))))
":"
default-directory
#(" " 0 1
(help-echo
"mouse-1: select window, mouse-2: delete others ..."))
(line-number-mode " Line %l ")
global-mode-string
#(" %[(" 0 6
(help-echo
"mouse-1: select window, mouse-2: delete others ..."))
(:eval (mode-line-mode-name))
mode-line-process
minor-mode-alist
#("%n" 0 2 (help-echo "mouse-2: widen" local-map (keymap ...)))
")%] "
(-3 . "%P")
;; "-%-"
)))
Here, I redefine the default mode line. Most of the parts are from the
original; but I make a few changes. I set the _default_ mode line
format so as to permit various modes, such as Info, to override it.
Many elements in the list are self-explanatory: `mode-line-modified'
is a variable that tells whether the buffer has been modified,
`mode-name' tells the name of the mode, and so on. However, the format
looks complicated because of two features we have not discussed.
The first string in the mode line is a dash or hyphen, `-'. In the
old days, it would have been specified simply as `"-"'. But nowadays,
Emacs can add properties to a string, such as highlighting or, as in
this case, a help feature. If you place your mouse cursor over the
hyphen, some help information appears (By default, you must wait one
second before the information appears. You can change that timing by
changing the value of `tooltip-delay'.)
The new string format has a special syntax:
#("-" 0 1 (help-echo "mouse-1: select window, ..."))
The `#(' begins a list. The first element of the list is the string
itself, just one `-'. The second and third elements specify the range
over which the fourth element applies. A range starts _after_ a
character, so a zero means the range starts just before the first
character; a 1 means that the range ends just after the first
character. The third element is the property for the range. It
consists of a property list, a property name, in this case,
`help-echo', followed by a value, in this case, a string. The second,
third, and fourth elements of this new string format can be repeated.
*Note Text Properties in String: (elisp)Text Props and Strings, and
see *Note Mode Line Format: (elisp)Mode Line Format, for more
information.
`mode-line-buffer-identification' displays the current buffer name.
It is a list beginning `(#("%12b" 0 4 ...'. The `#(' begins the list.
The `"%12b"' displays the current buffer name, using the
`buffer-name' function with which we are familiar; the `12' specifies
the maximum number of characters that will be displayed. When a name
has fewer characters, whitespace is added to fill out to this number.
(Buffer names can and often should be longer than 12 characters; this
length works well in a typical 80 column wide window.)
`:eval' is a new feature in GNU Emacs version 21. It says to
evaluate the following form and use the result as a string to display.
In this case, the expression displays the first component of the full
system name. The end of the first component is a `.' (`period'), so I
use the `string-match' function to tell me the length of the first
component. The substring from the zeroth character to that length is
the name of the machine.
This is the expression:
(:eval (substring
(system-name) 0 (string-match "\\..+" (system-name))))
`%[' and `%]' cause a pair of square brackets to appear for each
recursive editing level. `%n' says `Narrow' when narrowing is in
effect. `%P' tells you the percentage of the buffer that is above the
bottom of the window, or `Top', `Bottom', or `All'. (A lower case `p'
tell you the percentage above the _top_ of the window.) `%-' inserts
enough dashes to fill out the line.
Remember, "You don't have to like Emacs to like it" -- your own
Emacs can have different colors, different commands, and different keys
than a default Emacs.
On the other hand, if you want to bring up a plain `out of the box'
Emacs, with no customization, type:
emacs -q
This will start an Emacs that does _not_ load your `~/.emacs'
initialization file. A plain, default Emacs. Nothing more.
File: emacs-lisp-intro.info, Node: Debugging, Next: Conclusion, Prev: Emacs Initialization, Up: Top
Debugging
*********
GNU Emacs has two debuggers, `debug' and `edebug'. The first is
built into the internals of Emacs and is always with you; the second
requires that you instrument a function before you can use it.
Both debuggers are described extensively in *Note Debugging Lisp
Programs: (elisp)Debugging. In this chapter, I will walk through a
short example of each.
* Menu:
* debug:: How to use the built-in debugger.
* debug-on-entry:: Start debugging when you call a function.
* debug-on-quit:: Start debugging when you quit with C-g.
* edebug:: How to use Edebug, a source level debugger.
* Debugging Exercises::
File: emacs-lisp-intro.info, Node: debug, Next: debug-on-entry, Prev: Debugging, Up: Debugging
`debug'
=======
Suppose you have written a function definition that is intended to
return the sum of the numbers 1 through a given number. (This is the
`triangle' function discussed earlier. *Note Example with Decrementing
Counter: Decrementing Example, for a discussion.)
However, your function definition has a bug. You have mistyped `1='
for `1-'. Here is the broken definition:
(defun triangle-bugged (number)
"Return sum of numbers 1 through NUMBER inclusive."
(let ((total 0))
(while (> number 0)
(setq total (+ total number))
(setq number (1= number))) ; Error here.
total))
If you are reading this in Info, you can evaluate this definition in
the normal fashion. You will see `triangle-bugged' appear in the echo
area.
Now evaluate the `triangle-bugged' function with an argument of 4:
(triangle-bugged 4)
In GNU Emacs version 21, you will create and enter a `*Backtrace*'
buffer that says:
---------- Buffer: *Backtrace* ----------
Debugger entered--Lisp error: (void-function 1=)
(1= number)
(setq number (1= number))
(while (> number 0) (setq total (+ total number))
(setq number (1= number)))
(let ((total 0)) (while (> number 0) (setq total ...)
(setq number ...)) total)
triangle-bugged(4)
eval((triangle-bugged 4))
eval-last-sexp-1(nil)
eval-last-sexp(nil)
call-interactively(eval-last-sexp)
---------- Buffer: *Backtrace* ----------
(I have reformatted this example slightly; the debugger does not fold
long lines. As usual, you can quit the debugger by typing `q' in the
`*Backtrace*' buffer.)
In practice, for a bug as simple as this, the `Lisp error' line will
tell you what you need to know to correct the definition. The function
`1=' is `void'.
In GNU Emacs 20 and before, you will see:
Symbol's function definition is void: 1=
which has the same meaning as the `*Backtrace*' buffer line in version
21.
However, suppose you are not quite certain what is going on? You
can read the complete backtrace.
In this case, you need to run GNU Emacs 21, which automatically
starts the debugger that puts you in the `*Backtrace*' buffer; or else,
you need to start the debugger manually as described below.
Read the `*Backtrace*' buffer from the bottom up; it tells you what
Emacs did that led to the error. Emacs made an interactive call to
`C-x C-e' (`eval-last-sexp'), which led to the evaluation of the
`triangle-bugged' expression. Each line above tells you what the Lisp
interpreter evaluated next.
The third line from the top of the buffer is
(setq number (1= number))
Emacs tried to evaluate this expression; in order to do so, it tried to
evaluate the inner expression shown on the second line from the top:
(1= number)
This is where the error occurred; as the top line says:
Debugger entered--Lisp error: (void-function 1=)
You can correct the mistake, re-evaluate the function definition, and
then run your test again.
File: emacs-lisp-intro.info, Node: debug-on-entry, Next: debug-on-quit, Prev: debug, Up: Debugging
`debug-on-entry'
================
GNU Emacs 21 starts the debugger automatically when your function has
an error. GNU Emacs version 20 and before did not; it simply presented
you with an error message. You had to start the debugger manually.
You can start the debugger manually for all versions of Emacs; the
advantage is that the debugger runs even if you do not have a bug in
your code. Sometimes your code will be free of bugs!
You can enter the debugger when you call the function by calling
`debug-on-entry'.
Type:
M-x debug-on-entry RET triangle-bugged RET
Now, evaluate the following:
(triangle-bugged 5)
All versions of Emacs will create a `*Backtrace*' buffer and tell you
that it is beginning to evaluate the `triangle-bugged' function:
---------- Buffer: *Backtrace* ----------
Debugger entered--entering a function:
* triangle-bugged(5)
eval((triangle-bugged 5))
eval-last-sexp-1(nil)
eval-last-sexp(nil)
call-interactively(eval-last-sexp)
---------- Buffer: *Backtrace* ----------
In the `*Backtrace*' buffer, type `d'. Emacs will evaluate the
first expression in `triangle-bugged'; the buffer will look like this:
---------- Buffer: *Backtrace* ----------
Debugger entered--beginning evaluation of function call form:
* (let ((total 0)) (while (> number 0) (setq total ...)
(setq number ...)) total)
* triangle-bugged(5)
eval((triangle-bugged 5))
eval-last-sexp-1(nil)
eval-last-sexp(nil)
call-interactively(eval-last-sexp)
---------- Buffer: *Backtrace* ----------
Now, type `d' again, eight times, slowly. Each time you type `d',
Emacs will evaluate another expression in the function definition.
Eventually, the buffer will look like this:
---------- Buffer: *Backtrace* ----------
Debugger entered--beginning evaluation of function call form:
* (setq number (1= number))
* (while (> number 0) (setq total (+ total number))
(setq number (1= number)))
* (let ((total 0)) (while (> number 0) (setq total ...)
(setq number ...)) total)
* triangle-bugged(5)
eval((triangle-bugged 5))
eval-last-sexp-1(nil)
eval-last-sexp(nil)
call-interactively(eval-last-sexp)
---------- Buffer: *Backtrace* ----------
Finally, after you type `d' two more times, Emacs will reach the error,
and the top two lines of the `*Backtrace*' buffer will look like this:
---------- Buffer: *Backtrace* ----------
Debugger entered--Lisp error: (void-function 1=)
* (1= number)
...
---------- Buffer: *Backtrace* ----------
By typing `d', you were able to step through the function.
You can quit a `*Backtrace*' buffer by typing `q' in it; this quits
the trace, but does not cancel `debug-on-entry'.
To cancel the effect of `debug-on-entry', call
`cancel-debug-on-entry' and the name of the function, like this:
M-x cancel-debug-on-entry RET triangle-bugged RET
(If you are reading this in Info, cancel `debug-on-entry' now.)
File: emacs-lisp-intro.info, Node: debug-on-quit, Next: edebug, Prev: debug-on-entry, Up: Debugging
`debug-on-quit' and `(debug)'
=============================
In addition to setting `debug-on-error' or calling `debug-on-entry',
there are two other ways to start `debug'.
You can start `debug' whenever you type `C-g' (`keyboard-quit') by
setting the variable `debug-on-quit' to `t'. This is useful for
debugging infinite loops.
Or, you can insert a line that says `(debug)' into your code where
you want the debugger to start, like this:
(defun triangle-bugged (number)
"Return sum of numbers 1 through NUMBER inclusive."
(let ((total 0))
(while (> number 0)
(setq total (+ total number))
(debug) ; Start debugger.
(setq number (1= number))) ; Error here.
total))
The `debug' function is described in detail in *Note The Lisp
Debugger: (elisp)Debugger.
File: emacs-lisp-intro.info, Node: edebug, Next: Debugging Exercises, Prev: debug-on-quit, Up: Debugging
The `edebug' Source Level Debugger
==================================
Edebug is a source level debugger. Edebug normally displays the
source of the code you are debugging, with an arrow at the left that
shows which line you are currently executing.
You can walk through the execution of a function, line by line, or
run quickly until reaching a "breakpoint" where execution stops.
Edebug is described in *Note Edebug: (elisp)edebug.
Here is a bugged function definition for `triangle-recursively'.
*Note Recursion in place of a counter: Recursive triangle function, for
a review of it.
(defun triangle-recursively-bugged (number)
"Return sum of numbers 1 through NUMBER inclusive.
Uses recursion."
(if (= number 1)
1
(+ number
(triangle-recursively-bugged
(1= number))))) ; Error here.
Normally, you would install this definition by positioning your cursor
after the function's closing parenthesis and typing `C-x C-e'
(`eval-last-sexp') or else by positioning your cursor within the
definition and typing `C-M-x' (`eval-defun'). (By default, the
`eval-defun' command works only in Emacs Lisp mode or in Lisp
Interactive mode.)
However, to prepare this function definition for Edebug, you must
first "instrument" the code using a different command. You can do this
by positioning your cursor within the definition and typing
M-x edebug-defun RET
This will cause Emacs to load Edebug automatically if it is not already
loaded, and properly instrument the function.
After instrumenting the function, place your cursor after the
following expression and type `C-x C-e' (`eval-last-sexp'):
(triangle-recursively-bugged 3)
You will be jumped back to the source for `triangle-recursively-bugged'
and the cursor positioned at the beginning of the `if' line of the
function. Also, you will see an arrowhead at the left hand side of
that line. The arrowhead marks the line where the function is
executing. (In the following examples, we show the arrowhead with
`=>'; in a windowing system, you may see the arrowhead as a solid
triangle in the window `fringe'.)
=>-!-(if (= number 1)
In the example, the location of point is displayed as `-!-' (in a
printed book, it is displayed with a five pointed star).
If you now press <SPC>, point will move to the next expression to be
executed; the line will look like this:
=>(if -!-(= number 1)
As you continue to press <SPC>, point will move from expression to
expression. At the same time, whenever an expression returns a value,
that value will be displayed in the echo area. For example, after you
move point past `number', you will see the following:
Result: 3 = C-c
This means the value of `number' is 3, which is ASCII `control-c' (the
third letter of the alphabet).
You can continue moving through the code until you reach the line
with the error. Before evaluation, that line looks like this:
=> -!-(1= number))))) ; Error here.
When you press <SPC> once again, you will produce an error message that
says:
Symbol's function definition is void: 1=
This is the bug.
Press `q' to quit Edebug.
To remove instrumentation from a function definition, simply
re-evaluate it with a command that does not instrument it. For
example, you could place your cursor after the definition's closing
parenthesis and type `C-x C-e'.
Edebug does a great deal more than walk with you through a function.
You can set it so it races through on its own, stopping only at an
error or at specified stopping points; you can cause it to display the
changing values of various expressions; you can find out how many times
a function is called, and more.
Edebug is described in *Note Edebug: (elisp)edebug.
File: emacs-lisp-intro.info, Node: Debugging Exercises, Prev: edebug, Up: Debugging
Debugging Exercises
===================
* Install the `count-words-region' function and then cause it to
enter the built-in debugger when you call it. Run the command on a
region containing two words. You will need to press `d' a
remarkable number of times. On your system, is a `hook' called
after the command finishes? (For information on hooks, see *Note
Command Loop Overview: (elisp)Command Overview.)
* Copy `count-words-region' into the `*scratch*' buffer, instrument
the function for Edebug, and walk through its execution. The
function does not need to have a bug, although you can introduce
one if you wish. If the function lacks a bug, the walk-through
completes without problems.
* While running Edebug, type `?' to see a list of all the Edebug
commands. (The `global-edebug-prefix' is usually `C-x X', i.e.
`<CTL>-x' followed by an upper case `X'; use this prefix for
commands made outside of the Edebug debugging buffer.)
* In the Edebug debugging buffer, use the `p'
(`edebug-bounce-point') command to see where in the region the
`count-words-region' is working.
* Move point to some spot further down function and then type the
`h' (`edebug-goto-here') command to jump to that location.
* Use the `t' (`edebug-trace-mode') command to cause Edebug to walk
through the function on its own; use an upper case `T' for
`edebug-Trace-fast-mode'.
* Set a breakpoint, then run Edebug in Trace mode until it reaches
the stopping point.
File: emacs-lisp-intro.info, Node: Conclusion, Next: the-the, Prev: Debugging, Up: Top
Conclusion
**********
We have now reached the end of this Introduction. You have now
learned enough about programming in Emacs Lisp to set values, to write
simple `.emacs' files for yourself and your friends, and write simple
customizations and extensions to Emacs.
This is a place to stop. Or, if you wish, you can now go onward, and
teach yourself.
You have learned some of the basic nuts and bolts of programming.
But only some. There are a great many more brackets and hinges that are
easy to use that we have not touched.
A path you can follow right now lies among the sources to GNU Emacs
and in *Note The GNU Emacs Lisp Reference Manual: (elisp)Top.
The Emacs Lisp sources are an adventure. When you read the sources
and come across a function or expression that is unfamiliar, you need to
figure out or find out what it does.
Go to the Reference Manual. It is a thorough, complete, and fairly
easy-to-read description of Emacs Lisp. It is written not only for
experts, but for people who know what you know. (The `Reference
Manual' comes with the standard GNU Emacs distribution. Like this
introduction, it comes as a Texinfo source file, so you can read it
on-line and as a typeset, printed book.)
Go to the other on-line help that is part of GNU Emacs: the on-line
documentation for all functions, and `find-tags', the program that
takes you to sources.
Here is an example of how I explore the sources. Because of its
name, `simple.el' is the file I looked at first, a long time ago. As
it happens some of the functions in `simple.el' are complicated, or at
least look complicated at first sight. The `open-line' function, for
example, looks complicated.
You may want to walk through this function slowly, as we did with the
`forward-sentence' function. (*Note forward-sentence::.) Or you may
want to skip that function and look at another, such as `split-line'.
You don't need to read all the functions. According to
`count-words-in-defun', the `split-line' function contains 27 words and
symbols.
Even though it is short, `split-line' contains four expressions we
have not studied: `skip-chars-forward', `indent-to', `current-column'
and `?\n'.
Consider the `skip-chars-forward' function. (It is part of the
function definition for `back-to-indentation', which is shown in *Note
Review: Review.)
In GNU Emacs, you can find out more about `skip-chars-forward' by
typing `C-h f' (`describe-function') and the name of the function.
This gives you the function documentation.
You may be able to guess what is done by a well named function such
as `indent-to'; or you can look it up, too. Incidentally, the
`describe-function' function itself is in `help.el'; it is one of those
long, but decipherable functions. You can look up `describe-function'
using the `C-h f' command!
In this instance, since the code is Lisp, the `*Help*' buffer
contains the name of the library containing the function's source. You
can put point over the name of the library and press the RET key, which
in this situation is bound to `help-follow', and be taken directly to
the source, in the same way as `M-.' (`find-tag').
The definition for `describe-function' illustrates how to customize
the `interactive' expression without using the standard character
codes; and it shows how to create a temporary buffer.
(The `indent-to' function is written in C rather than Emacs Lisp; it
is a `built-in' function. `help-follow' only provides you with the
documentation of a built-in function; it does not take you to the
source. But `find-tag' will take you to the source, if properly set
up.)
You can look at a function's source using `find-tag', which is bound
to `M-.' Finally, you can find out what the Reference Manual has to
say by visiting the manual in Info, and typing `i' (`Info-index') and
the name of the function, or by looking up `skip-chars-forward' in the
index to a printed copy of the manual.
Similarly, you can find out what is meant by `?\n'. You can try
using `Info-index' with `?\n'. It turns out that this action won't
help; but don't give up. If you search the index for `\n' without the
`?', you will be taken directly to the relevant section of the manual.
(*Note Character Type: (elisp)Character Type. `?\n' stands for the
newline character.)
Other interesting source files include `paragraphs.el',
`loaddefs.el', and `loadup.el'. The `paragraphs.el' file includes
short, easily understood functions as well as longer ones. The
`loaddefs.el' file contains the many standard autoloads and many
keymaps. I have never looked at it all; only at parts. `loadup.el' is
the file that loads the standard parts of Emacs; it tells you a great
deal about how Emacs is built. (*Note Building Emacs: (elisp)Building
Emacs, for more about building.)
As I said, you have learned some nuts and bolts; however, and very
importantly, we have hardly touched major aspects of programming; I
have said nothing about how to sort information, except to use the
predefined `sort' function; I have said nothing about how to store
information, except to use variables and lists; I have said nothing
about how to write programs that write programs. These are topics for
another, and different kind of book, a different kind of learning.
What you have done is learn enough for much practical work with GNU
Emacs. What you have done is get started. This is the end of a
beginning.
File: emacs-lisp-intro.info, Node: the-the, Next: Kill Ring, Prev: Conclusion, Up: Top
The `the-the' Function
**********************
Sometimes when you you write text, you duplicate words--as with "you
you" near the beginning of this sentence. I find that most frequently,
I duplicate "the'; hence, I call the function for detecting duplicated
words, `the-the'.
As a first step, you could use the following regular expression to
search for duplicates:
\\(\\w+[ \t\n]+\\)\\1
This regexp matches one or more word-constituent characters followed by
one or more spaces, tabs, or newlines. However, it does not detect
duplicated words on different lines, since the ending of the first
word, the end of the line, is different from the ending of the second
word, a space. (For more information about regular expressions, see
*Note Regular Expression Searches: Regexp Search, as well as *Note
Syntax of Regular Expressions: (emacs)Regexps, and *Note Regular
Expressions: (elisp)Regular Expressions.)
You might try searching just for duplicated word-constituent
characters but that does not work since the pattern detects doubles
such as the two occurrences of `th' in `with the'.
Another possible regexp searches for word-constituent characters
followed by non-word-constituent characters, reduplicated. Here,
`\\w+' matches one or more word-constituent characters and `\\W*'
matches zero or more non-word-constituent characters.
\\(\\(\\w+\\)\\W*\\)\\1
Again, not useful.
Here is the pattern that I use. It is not perfect, but good enough.
`\\b' matches the empty string, provided it is at the beginning or end
of a word; `[^@ \n\t]+' matches one or more occurrences of any
characters that are _not_ an @-sign, space, newline, or tab.
\\b\\([^@ \n\t]+\\)[ \n\t]+\\1\\b
One can write more complicated expressions, but I found that this
expression is good enough, so I use it.
Here is the `the-the' function, as I include it in my `.emacs' file,
along with a handy global key binding:
(defun the-the ()
"Search forward for for a duplicated word."
(interactive)
(message "Searching for for duplicated words ...")
(push-mark)
;; This regexp is not perfect
;; but is fairly good over all:
(if (re-search-forward
"\\b\\([^@ \n\t]+\\)[ \n\t]+\\1\\b" nil 'move)
(message "Found duplicated word.")
(message "End of buffer")))
;; Bind `the-the' to C-c \
(global-set-key "\C-c\\" 'the-the)
Here is test text:
one two two three four five
five six seven
You can substitute the other regular expressions shown above in the
function definition and try each of them on this list.
File: emacs-lisp-intro.info, Node: Kill Ring, Next: Full Graph, Prev: the-the, Up: Top
Handling the Kill Ring
**********************
The kill ring is a list that is transformed into a ring by the
workings of the `rotate-yank-pointer' function. The `yank' and
`yank-pop' commands use the `rotate-yank-pointer' function. This
appendix describes the `rotate-yank-pointer' function as well as both
the `yank' and the `yank-pop' commands.
* Menu:
* rotate-yank-pointer:: Move a pointer along a list and around.
* yank:: Paste a copy of a clipped element.
* yank-pop:: Insert first element pointed to.
File: emacs-lisp-intro.info, Node: rotate-yank-pointer, Next: yank, Prev: Kill Ring, Up: Kill Ring
The `rotate-yank-pointer' Function
==================================
The `rotate-yank-pointer' function changes the element in the kill
ring to which `kill-ring-yank-pointer' points. For example, it can
change `kill-ring-yank-pointer' from pointing to the second element to
point to the third element.
Here is the code for `rotate-yank-pointer':
(defun rotate-yank-pointer (arg)
"Rotate the yanking point in the kill ring."
(interactive "p")
(let ((length (length kill-ring)))
(if (zerop length)
;; then-part
(error "Kill ring is empty")
;; else-part
(setq kill-ring-yank-pointer
(nthcdr (% (+ arg
(- length
(length
kill-ring-yank-pointer)))
length)
kill-ring)))))
* Menu:
* Understanding rotate-yk-ptr::
* rotate-yk-ptr body:: The body of `rotate-yank-pointer'.
File: emacs-lisp-intro.info, Node: Understanding rotate-yk-ptr, Next: rotate-yk-ptr body, Prev: rotate-yank-pointer, Up: rotate-yank-pointer
`rotate-yank-pointer' in Outline
--------------------------------
The `rotate-yank-pointer' function looks complex, but as usual, it
can be understood by taking it apart piece by piece. First look at it
in skeletal form:
(defun rotate-yank-pointer (arg)
"Rotate the yanking point in the kill ring."
(interactive "p")
(let VARLIST
BODY...)
This function takes one argument, called `arg'. It has a brief
documentation string; and it is interactive with a small `p', which
means that the argument must be a processed prefix passed to the
function as a number.
The body of the function definition is a `let' expression, which
itself has a body as well as a VARLIST.
The `let' expression declares a variable that will be only usable
within the bounds of this function. This variable is called `length'
and is bound to a value that is equal to the number of items in the
kill ring. This is done by using the function called `length'. (Note
that this function has the same name as the variable called `length';
but one use of the word is to name the function and the other is to
name the variable. The two are quite distinct. Similarly, an English
speaker will distinguish between the meanings of the word `ship' when
he says: "I must ship this package immediately." and "I must get aboard
the ship immediately.")
The function `length' tells the number of items there are in a list,
so `(length kill-ring)' returns the number of items there are in the
kill ring.
File: emacs-lisp-intro.info, Node: rotate-yk-ptr body, Prev: Understanding rotate-yk-ptr, Up: rotate-yank-pointer
The Body of `rotate-yank-pointer'
---------------------------------
The body of `rotate-yank-pointer' is a `let' expression and the body
of the `let' expression is an `if' expression.
The purpose of the `if' expression is to find out whether there is
anything in the kill ring. If the kill ring is empty, the `error'
function stops evaluation of the function and prints a message in the
echo area. On the other hand, if the kill ring has something in it, the
work of the function is done.
Here is the if-part and then-part of the `if' expression:
(if (zerop length) ; if-part
(error "Kill ring is empty") ; then-part
...
If there is not anything in the kill ring, its length must be zero and
an error message sent to the user: `Kill ring is empty'. The `if'
expression uses the function `zerop' which returns true if the value it
is testing is zero. When `zerop' tests true, the then-part of the `if'
is evaluated. The then-part is a list starting with the function
`error', which is a function that is similar to the `message' function
(*note message::), in that it prints a one-line message in the echo
area. However, in addition to printing a message, `error' also stops
evaluation of the function within which it is embedded. This means
that the rest of the function will not be evaluated if the length of
the kill ring is zero.
* Menu:
* Digression concerning error:: How to mislead humans, but not computers.
* rotate-yk-ptr else-part:: The else-part of the `if' expression.
* Remainder Function:: The remainder, `%', function.
* rotate-yk-ptr remainder:: Using `%' in `rotate-yank-pointer'.
* kill-rng-yk-ptr last elt:: Pointing to the last element.
File: emacs-lisp-intro.info, Node: Digression concerning error, Next: rotate-yk-ptr else-part, Prev: rotate-yk-ptr body, Up: rotate-yk-ptr body
Digression about the word `error'
.................................
(In my opinion, it is slightly misleading, at least to humans, to use
the term `error' as the name of the `error' function. A better term
would be `cancel'. Strictly speaking, of course, you cannot point to,
much less rotate a pointer to a list that has no length, so from the
point of view of the computer, the word `error' is correct. But a
human expects to attempt this sort of thing, if only to find out
whether the kill ring is full or empty. This is an act of exploration.
(From the human point of view, the act of exploration and discovery
is not necessarily an error, and therefore should not be labelled as
one, even in the bowels of a computer. As it is, the code in Emacs
implies that a human who is acting virtuously, by exploring his or her
environment, is making an error. This is bad. Even though the computer
takes the same steps as it does when there is an `error', a term such as
`cancel' would have a clearer connotation.)
File: emacs-lisp-intro.info, Node: rotate-yk-ptr else-part, Next: Remainder Function, Prev: Digression concerning error, Up: rotate-yk-ptr body
The else-part of the `if' expression
....................................
The else-part of the `if' expression is dedicated to setting the
value of `kill-ring-yank-pointer' when the kill ring has something in
it. The code looks like this:
(setq kill-ring-yank-pointer
(nthcdr (% (+ arg
(- length
(length kill-ring-yank-pointer)))
length)
kill-ring)))))
This needs some examination. Clearly, `kill-ring-yank-pointer' is
being set to be equal to some CDR of the kill ring, using the `nthcdr'
function that is described in an earlier section. (*Note
copy-region-as-kill::.) But exactly how does it do this?
Before looking at the details of the code let's first consider the
purpose of the `rotate-yank-pointer' function.
The `rotate-yank-pointer' function changes what
`kill-ring-yank-pointer' points to. If `kill-ring-yank-pointer' starts
by pointing to the first element of a list, a call to
`rotate-yank-pointer' causes it to point to the second element; and if
`kill-ring-yank-pointer' points to the second element, a call to
`rotate-yank-pointer' causes it to point to the third element. (And if
`rotate-yank-pointer' is given an argument greater than 1, it jumps the
pointer that many elements.)
The `rotate-yank-pointer' function uses `setq' to reset what the
`kill-ring-yank-pointer' points to. If `kill-ring-yank-pointer' points
to the first element of the kill ring, then, in the simplest case, the
`rotate-yank-pointer' function must cause it to point to the second
element. Put another way, `kill-ring-yank-pointer' must be reset to
have a value equal to the CDR of the kill ring.
That is, under these circumstances,
(setq kill-ring-yank-pointer
("some text" "a different piece of text" "yet more text"))
(setq kill-ring
("some text" "a different piece of text" "yet more text"))
the code should do this:
(setq kill-ring-yank-pointer (cdr kill-ring))
As a result, the `kill-ring-yank-pointer' will look like this:
kill-ring-yank-pointer
=> ("a different piece of text" "yet more text"))
The actual `setq' expression uses the `nthcdr' function to do the
job.
As we have seen before (*note nthcdr::), the `nthcdr' function works
by repeatedly taking the CDR of a list--it takes the CDR of the CDR of
the CDR ...
The two following expressions produce the same result:
(setq kill-ring-yank-pointer (cdr kill-ring))
(setq kill-ring-yank-pointer (nthcdr 1 kill-ring))
In the `rotate-yank-pointer' function, however, the first argument
to `nthcdr' is a rather complex looking expression with lots of
arithmetic inside of it:
(% (+ arg
(- length
(length kill-ring-yank-pointer)))
length)
As usual, we need to look at the most deeply embedded expression
first and then work our way towards the light.
The most deeply embedded expression is `(length
kill-ring-yank-pointer)'. This finds the length of the current value of
the `kill-ring-yank-pointer'. (Remember that the
`kill-ring-yank-pointer' is the name of a variable whose value is a
list.)
The measurement of the length is inside the expression:
(- length (length kill-ring-yank-pointer))
In this expression, the first `length' is the variable that was
assigned the length of the kill ring in the `let' statement at the
beginning of the function. (One might think this function would be
clearer if the variable `length' were named `length-of-kill-ring'
instead; but if you look at the text of the whole function, you will
see that it is so short that naming this variable `length' is not a
bother, unless you are pulling the function apart into very tiny pieces
as we are doing here.)
So the line `(- length (length kill-ring-yank-pointer))' tells the
difference between the length of the kill ring and the length of the
list whose name is `kill-ring-yank-pointer'.
To see how all this fits into the `rotate-yank-pointer' function,
let's begin by analyzing the case where `kill-ring-yank-pointer' points
to the first element of the kill ring, just as `kill-ring' does, and
see what happens when `rotate-yank-pointer' is called with an argument
of 1.
The variable `length' and the value of the expression `(length
kill-ring-yank-pointer)' will be the same since the variable `length'
is the length of the kill ring and the `kill-ring-yank-pointer' is
pointing to the whole kill ring. Consequently, the value of
(- length (length kill-ring-yank-pointer))
will be zero. Since the value of `arg' will be 1, this will mean that
the value of the whole expression
(+ arg (- length (length kill-ring-yank-pointer)))
will be 1.
Consequently, the argument to `nthcdr' will be found as the result of
the expression
(% 1 length)
File: emacs-lisp-intro.info, Node: Remainder Function, Next: rotate-yk-ptr remainder, Prev: rotate-yk-ptr else-part, Up: rotate-yk-ptr body
The `%' remainder function
..........................
To understand `(% 1 length)', we need to understand `%'. According
to its documentation (which I just found by typing `C-h f % <RET>'),
the `%' function returns the remainder of its first argument divided by
its second argument. For example, the remainder of 5 divided by 2 is
1. (2 goes into 5 twice with a remainder of 1.)
What surprises people who don't often do arithmetic is that a smaller
number can be divided by a larger number and have a remainder. In the
example we just used, 5 was divided by 2. We can reverse that and ask,
what is the result of dividing 2 by 5? If you can use fractions, the
answer is obviously 2/5 or .4; but if, as here, you can only use whole
numbers, the result has to be something different. Clearly, 5 can go
into 2 zero times, but what of the remainder? To see what the answer
is, consider a case that has to be familiar from childhood:
* 5 divided by 5 is 1 with a remainder of 0;
* 6 divided by 5 is 1 with a remainder of 1;
* 7 divided by 5 is 1 with a remainder of 2.
* Similarly, 10 divided by 5 is 2 with a remainder of 0;
* 11 divided by 5 is 2 with a remainder of 1;
* 12 divided by 5 is 1 with a remainder of 2.
By considering the cases as parallel, we can see that
* zero divided by 5 must be zero with a remainder of zero;
* 1 divided by 5 must be zero with a remainder of 1;
* 2 divided by 5 must be zero with a remainder of 2;
and so on.
So, in this code, if the value of `length' is 5, then the result of
evaluating
(% 1 5)
is 1. (I just checked this by placing the cursor after the expression
and typing `C-x C-e'. Indeed, 1 is printed in the echo area.)
File: emacs-lisp-intro.info, Node: rotate-yk-ptr remainder, Next: kill-rng-yk-ptr last elt, Prev: Remainder Function, Up: rotate-yk-ptr body
Using `%' in `rotate-yank-pointer'
..................................
When the `kill-ring-yank-pointer' points to the beginning of the
kill ring, and the argument passed to `rotate-yank-pointer' is 1, the
`%' expression returns 1:
(- length (length kill-ring-yank-pointer))
=> 0
therefore,
(+ arg (- length (length kill-ring-yank-pointer)))
=> 1
and consequently:
(% (+ arg (- length (length kill-ring-yank-pointer)))
length)
=> 1
regardless of the value of `length'.
As a result of this, the `setq kill-ring-yank-pointer' expression
simplifies to:
(setq kill-ring-yank-pointer (nthcdr 1 kill-ring))
What it does is now easy to understand. Instead of pointing as it did
to the first element of the kill ring, the `kill-ring-yank-pointer' is
set to point to the second element.
Clearly, if the argument passed to `rotate-yank-pointer' is two, then
the `kill-ring-yank-pointer' is set to `(nthcdr 2 kill-ring)'; and so
on for different values of the argument.
Similarly, if the `kill-ring-yank-pointer' starts out pointing to
the second element of the kill ring, its length is shorter than the
length of the kill ring by 1, so the computation of the remainder is
based on the expression `(% (+ arg 1) length)'. This means that the
`kill-ring-yank-pointer' is moved from the second element of the kill
ring to the third element if the argument passed to
`rotate-yank-pointer' is 1.
File: emacs-lisp-intro.info, Node: kill-rng-yk-ptr last elt, Prev: rotate-yk-ptr remainder, Up: rotate-yk-ptr body
Pointing to the last element
............................
The final question is, what happens if the `kill-ring-yank-pointer'
is set to the _last_ element of the kill ring? Will a call to
`rotate-yank-pointer' mean that nothing more can be taken from the kill
ring? The answer is no. What happens is different and useful. The
`kill-ring-yank-pointer' is set to point to the beginning of the kill
ring instead.
Let's see how this works by looking at the code, assuming the length
of the kill ring is 5 and the argument passed to `rotate-yank-pointer'
is 1. When the `kill-ring-yank-pointer' points to the last element of
the kill ring, its length is 1. The code looks like this:
(% (+ arg (- length (length kill-ring-yank-pointer))) length)
When the variables are replaced by their numeric values, the
expression looks like this:
(% (+ 1 (- 5 1)) 5)
This expression can be evaluated by looking at the most embedded inner
expression first and working outwards: The value of `(- 5 1)' is 4;
the sum of `(+ 1 4)' is 5; and the remainder of dividing 5 by 5 is
zero. So what `rotate-yank-pointer' will do is
(setq kill-ring-yank-pointer (nthcdr 0 kill-ring))
which will set the `kill-ring-yank-pointer' to point to the beginning
of the kill ring.
So what happens with successive calls to `rotate-yank-pointer' is
that it moves the `kill-ring-yank-pointer' from element to element in
the kill ring until it reaches the end; then it jumps back to the
beginning. And this is why the kill ring is called a ring, since by
jumping back to the beginning, it is as if the list has no end! (And
what is a ring, but an entity with no end?)
File: emacs-lisp-intro.info, Node: yank, Next: yank-pop, Prev: rotate-yank-pointer, Up: Kill Ring
`yank'
======
After learning about `rotate-yank-pointer', the code for the `yank'
function is almost easy. It has only one tricky part, which is the
computation of the argument to be passed to `rotate-yank-pointer'.
The code looks like this:
(defun yank (&optional arg)
"Reinsert the last stretch of killed text.
More precisely, reinsert the stretch of killed text most
recently killed OR yanked.
With just C-U as argument, same but put point in front
(and mark at end). With argument n, reinsert the nth
most recently killed stretch of killed text.
See also the command \\[yank-pop]."
(interactive "*P")
(rotate-yank-pointer (if (listp arg) 0
(if (eq arg '-) -1
(1- arg))))
(push-mark (point))
(insert (car kill-ring-yank-pointer))
(if (consp arg)
(exchange-point-and-mark)))
Glancing over this code, we can understand the last few lines readily
enough. The mark is pushed, that is, remembered; then the first element
(the CAR) of what the `kill-ring-yank-pointer' points to is inserted;
and then, if the argument passed the function is a `cons', point and
mark are exchanged so the point is put in the front of the inserted
text rather than at the end. This option is explained in the
documentation. The function itself is interactive with `"*P"'. This
means it will not work on a read-only buffer, and that the unprocessed
prefix argument is passed to the function.
* Menu:
* rotate-yk-ptr arg:: Pass the argument to `rotate-yank-pointer'.
* rotate-yk-ptr negative arg:: Pass a negative argument.
File: emacs-lisp-intro.info, Node: rotate-yk-ptr arg, Next: rotate-yk-ptr negative arg, Prev: yank, Up: yank
Passing the argument
....................
The hard part of `yank' is understanding the computation that
determines the value of the argument passed to `rotate-yank-pointer'.
Fortunately, it is not so difficult as it looks at first sight.
What happens is that the result of evaluating one or both of the
`if' expressions will be a number and that number will be the argument
passed to `rotate-yank-pointer'.
Laid out with comments, the code looks like this:
(if (listp arg) ; if-part
0 ; then-part
(if (eq arg '-) ; else-part, inner if
-1 ; inner if's then-part
(1- arg)))) ; inner if's else-part
This code consists of two `if' expression, one the else-part of the
other.
The first or outer `if' expression tests whether the argument passed
to `yank' is a list. Oddly enough, this will be true if `yank' is
called without an argument--because then it will be passed the value of
`nil' for the optional argument and an evaluation of `(listp nil)'
returns true! So, if no argument is passed to `yank', the argument
passed to `rotate-yank-pointer' inside of `yank' is zero. This means
the pointer is not moved and the first element to which
`kill-ring-yank-pointer' points is inserted, as we expect. Similarly,
if the argument for `yank' is `C-u', this will be read as a list, so
again, a zero will be passed to `rotate-yank-pointer'. (`C-u' produces
an unprocessed prefix argument of `(4)', which is a list of one
element.) At the same time, later in the function, this argument will
be read as a `cons' so point will be put in the front and mark at the
end of the insertion. (The `P' argument to `interactive' is designed
to provide these values for the case when an optional argument is not
provided or when it is `C-u'.)
The then-part of the outer `if' expression handles the case when
there is no argument or when it is `C-u'. The else-part handles the
other situations. The else-part is itself another `if' expression.
The inner `if' expression tests whether the argument is a minus
sign. (This is done by pressing the <META> and `-' keys at the same
time, or the <ESC> key and then the `-' key). In this case, the
`rotate-yank-pointer' function is passed `-1' as an argument. This
moves the `kill-ring-yank-pointer' backwards, which is what is desired.
If the true-or-false-test of the inner `if' expression is false
(that is, if the argument is not a minus sign), the else-part of the
expression is evaluated. This is the expression `(1- arg)'. Because
of the two `if' expressions, it will only occur when the argument is a
positive number or when it is a negative number (not just a minus sign
on its own). What `(1- arg)' does is decrement the number and return
it. (The `1-' function subtracts one from its argument.) This means
that if the argument to `rotate-yank-pointer' is 1, it is reduced to
zero, which means the first element to which `kill-ring-yank-pointer'
points is yanked back, as you would expect.